package org.wzh.spring.di.demos;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 假设我们要将ShoppingCart bean注入到单例StoreService bean的setter方法中.
 * 
 * 因为StoreService是一个单例的bean,会在Spring应用上下文加载的时候创建,当它创建的时候,Spring会试图将ShoppingCart bean注入到setShoppingCart()方法
 * 中.但是ShoppingCart bean是会话作用域的,此时并不存在.直到某个用户进入系统,创建了会话之后,才会出现ShoppingCart实例.
 * 另外,系统中将会有多个ShoppingCart实例:每个用户一个,我们并不想让Spring注入某个固定的ShoppingCart实例到StoreService中.我们希望的是当StoreService处理
 * 购物车功能时,它所使用的ShoppingCart实例恰好是当前会话所对象的那一个.
 * 
 * 						|-----------接口:会话/请求作用域的bean
 * 单例bean <---- 接口:作用域代理---------接口:会话/请求作用域的bean
 * 						|-----------接口:会话/请求作用域的bean
 * 						|-----------接口:会话/请求作用域的bean
 * Spring并不会将实际的ShoppingCart bean注入到StoreService中,Spring会注入一个到ShoppingCart bean的代理.这个代理会暴露与ShoppingCart相同的方法,
 * 所以StoreService会认为它就是一个购物车.但是,当StoreService调用ShoppingCart的方法时,代理会对其进行懒解析并将调用委托给会话作用域内真正的ShoppingCart bean.
 * 
 * 
 * proxyMode属性被试着成了ScopedMode.INTERFACES,这表明这个代理要实现ShoppingCart接口,并将调用委托给实现bean.
 * 如果ShoppingCart是接口而不是类的话,这是可以的(也是最为理想的代理模式).但如果ShoppingCart是一个具体的类的话,Spring就没有办法创建基于接口的代理了.
 * 此时,它必须使用CGLib来生成基于类的代理.
 * 所以,如果bean类型是具体类的话,我们必须要将proxyMode属性设置为ScopedProxyMode.TARGET_CLASS,以此来表明要以生成目标类扩展的方式创建代理.
 * @author Pear
 *
 */
@Component
public class StoreService {

	private ShoppingCart shoppingCart;
	
	@Autowired
	public void setShoppingCart(ShoppingCart shoppingCart) {
		this.shoppingCart = shoppingCart;
	}
}
